home *** CD-ROM | disk | FTP | other *** search
- #if 0
- #ident "@(#)glib.c 1.5 91/04/01 XGRASP"
- #endif
- /*-
- * glib.c - GRASP graphics librarian.
- *
- * Copyright (c) 1991 by Patrick J. Naughton
- *
- * Permission to use, copy, modify, and distribute this software and its
- * documentation for any purpose and without fee is hereby granted,
- * provided that the above copyright notice appear in all copies and that
- * both that copyright notice and this permission notice appear in
- * supporting documentation.
- *
- * This file is provided AS IS with no warranties of any kind. The author
- * shall have no liability with respect to the infringement of copyrights,
- * trade secrets or any patents by this file or any part thereof. In no
- * event will the author be liable for any lost revenue or profits or
- * other special, indirect and consequential damages.
- *
- * Comments and additions should be sent to the author:
- *
- * Patrick J. Naughton
- * Sun Microsystems
- * 2550 Garcia Ave, MS 10-20
- * Mountain View, CA 94043
- * (415) 336-1080
- *
- */
-
- #include <stdio.h>
- #include <stdlib.h>
- #include <assert.h>
- #include <string.h>
- #include <sys/types.h>
- #include <console.h>
- #include "match.h"
-
-
- char *pname;
- extern char *strrchr();
-
-
- #define TOO_MANY_ENTRIES 256
-
-
- typedef struct {
- char fname[14];
- long offset;
- long len;
- char *data;
- } FilenameStruct;
-
-
- typedef struct
- {
- short fileIndex;
-
- char fIsPattern;
- char fIsGoodPattern;
- short numMatched;
- short *pMatchedIndices;
-
- } MatchStruct, *MatchPtr;
-
-
- static void
- error(s1, s2, s3)
- char *s1, *s2, *s3;
- {
- fprintf(stderr, s1, pname, s2, s3);
- console_options.pause_atexit = 1;
- exit(1);
- }
-
-
- static u_short
- GetWord(fp)
- FILE *fp;
- {
- u_short b1 = (u_char) getc(fp);
- u_short b2 = (u_char) getc(fp);
-
- return (u_short) (b1 + b2 * 256);
- }
-
- static u_long
- GetLong(fp)
- FILE *fp;
- {
- u_long b1 = (u_char) getc(fp);
- u_long b2 = (u_char) getc(fp);
- u_long b3 = (u_char) getc(fp);
- u_long b4 = (u_char) getc(fp);
- u_long retVal = b1 + (b2 + (b3 + b4 * 256L) * 256L) * 256L;
-
-
- return retVal;
- }
-
-
- static void
- PutWord(fp, w)
- FILE *fp;
- unsigned int w;
- {
- unsigned char b1 = w & 255;
- unsigned char b2 = (w >> 8) & 255;
- putc(b1, fp);
- putc(b2, fp);
- }
-
-
- static void
- PutLong(fp, l)
- FILE *fp;
- unsigned long l;
- {
- unsigned char b1 = l & 255;
- unsigned char b2 = (l >> 8) & 255;
- unsigned char b3 = (l >> 16) & 255;
- unsigned char b4 = (l >> 24) & 255;
-
- putc(b1, fp);
- putc(b2, fp);
- putc(b3, fp);
- putc(b4, fp);
- }
-
-
- static char *
- lowerstr (char *s)
-
- {
- char *retVal = s;
-
- while (*s)
- {
- if (*s >= 'A' && *s <= 'Z')
- *s = *s + 'a' - 'A';
- s++;
- }
-
- return retVal;
- }
-
-
- static void
- extractfile(in, dir, i)
- FILE *in;
- FilenameStruct *dir;
- int i;
- {
- long len;
- char *data;
- FILE *out;
-
- fseek(in, dir[i].offset, 0);
- len = GetLong(in);
- len &= 0x00ffffff;
- data = (char *) malloc(len);
- if (!data)
- error("%s: not enough memory\n", NULL, NULL);
- fread(data, len, 1, in);
- out = fopen(dir[i].fname, "wb");
- if (!out)
- error("%s: error writing: %s\n", dir[i].fname, NULL);
- fwrite(data, len, 1, out);
- fclose(out);
- free(data);
- }
-
-
- static void
- writefile(fname, dir, nfiles)
- char *fname;
- FilenameStruct *dir;
- int nfiles;
- {
- FILE *out;
- int i;
- long offset = 2 + (nfiles + 1) * (13 + 4);
-
- out = fopen(fname, "wb");
- PutWord(out, (nfiles + 1) * (13 + 4));
- for (i = 0; i < nfiles; i++) {
- PutLong(out, offset);
- offset += dir[i].len + 4;
- fwrite(dir[i].fname, 13, 1, out);
- }
- PutLong(out, 0);
- fwrite(" ", 13, 1, out);
- for (i = 0; i < nfiles; i++) {
- PutLong(out, dir[i].len);
- fwrite(dir[i].data, dir[i].len, 1, out);
- }
- fclose(out);
- }
-
-
- static int
- findname(dir, nfiles, s)
- FilenameStruct *dir;
- int nfiles;
- char *s;
- {
- int i;
-
- if (dir)
- for (i = 0; i < nfiles; i++)
- if (!strcmp(dir[i].fname, s))
- return i;
- return -1;
- }
-
-
- static
- usage()
- {
- error("usage: %s [-dstuea] libname [files...]\n", NULL, NULL);
- }
-
-
- main(argc, argv)
- int argc;
- char *argv[];
- {
- int i;
- FILE *in;
- FILE *out;
- char *libfname;
- char *opfname;
- long nfiles = 0;
- FilenameStruct *dir = 0;
- int thefile = -1;
- short numSpecFiles = 0;
- short numFound = 0;
- MatchStruct *pFileIndices;
- int c;
- int dflg = 0;
- int sflg = 0;
- int tflg = 0;
- int uflg = 0;
- int eflg = 0;
- int aflg = 0;
-
- extern char *optarg;
- extern int optind;
- extern int mwf_ccommand (char ***av);
-
-
- argc = mwf_ccommand (&argv);
-
- pname = argv[0];
-
- if (argc == 1)
- usage();
- while ((c = egetopt(argc, argv, "hd:s:t:u:e:a:")) != -1)
- switch (c) {
- case 'h':
- printf("\nusage: glib [-dstuea] libname [files...]\n");
- printf("\n where the following commands are supported:\n\n");
- printf("\t-d delete file from library\n");
- printf("\t-s extended file list\n");
- printf("\t-t quick file list\n");
- printf("\t-u update (add) file to library\n");
- printf("\t-e extract file from library\n");
- printf("\t-a extract all files from library\n\n");
- exit(0);
- case 'd':
- if (uflg || eflg || aflg)
- usage();
- else
- dflg++;
- libfname = optarg;
- break;
- case 's':
- if (tflg)
- usage();
- else
- sflg++;
- libfname = optarg;
- break;
- case 't':
- if (sflg)
- usage();
- else
- tflg++;
- libfname = optarg;
- break;
- case 'u':
- if (dflg || eflg || aflg)
- usage();
- else
- uflg++;
- libfname = optarg;
- break;
- case 'e':
- if (dflg || uflg || aflg)
- usage();
- else
- eflg++;
- libfname = optarg;
- break;
- case 'a':
- if (dflg || uflg || eflg)
- usage();
- else
- aflg++;
- libfname = optarg;
- break;
- default:
- usage();
- }
-
- if (!libfname)
- usage();
-
- if ((dflg || uflg || eflg) && optind == argc)
- error ("%s: [-deu] no files specified after library name\n",
- (char *) NULL, (char *) NULL);
-
- /*...Build up a list of patterns to search for...*/
-
- if (dflg || eflg)
- {
- numSpecFiles = argc - optind;
-
- assert (
- pFileIndices = (MatchPtr) calloc ((size_t) numSpecFiles,
- (size_t) sizeof (MatchStruct)));
-
-
- for (i = 0; i < numSpecFiles; i++)
- {
- MatchPtr pFileIndex = pFileIndices + i;
- char *pSearchFor = argv[optind + i];
-
-
- pFileIndex->fileIndex = -1;
-
- /*...Accommodate regular expressions...*/
-
- if (pFileIndex->fIsPattern = is_pattern (lowerstr (pSearchFor)))
- {
- int error_type;
-
-
- pFileIndex->numMatched = 0;
-
- if (pFileIndex->fIsGoodPattern = is_valid_pattern (pSearchFor, &error_type))
- {
- /*...The following relies on malloc ((size_t) 0) returning a
- * legitimate value for subsequent realloc () calls.
- */
-
- pFileIndex->pMatchedIndices = (short *) malloc ((size_t) 0);
- }
- }
- }
- }
-
- if (!sflg && !tflg)
- console_options.pause_atexit = 0;
-
- in = fopen(libfname, "rb");
- if (!in && !uflg)
- error("%s: %s not found!\n", libfname, NULL);
-
- if (in /* != (FILE *) NULL */)
- {
- nfiles = (GetWord(in) / 17) - 1;
- if (0 >= nfiles || nfiles > TOO_MANY_ENTRIES)
- error ("%s: Not a GL archive (# entries = %ld)\n",
- (char *) nfiles, (char *) NULL);
-
- dir = (FilenameStruct *) malloc(nfiles * sizeof(FilenameStruct));
- for (i = 0; i < nfiles; i++)
- {
- dir[i].offset = GetLong(in);
- fread(dir[i].fname, 13, 1, in);
- dir[i].fname[13] = 0;
- (void) lowerstr (dir[i].fname);
-
- if (numSpecFiles /* > 0 */)
- {
- short j;
-
-
- for (j = 0; j < numSpecFiles; j++)
- {
- MatchPtr pFileIndex = pFileIndices + j;
-
-
- if (pFileIndex->fileIndex == -1)
- {
- char *pSearchFor = argv[optind + j];
-
-
- if (pFileIndex->fIsPattern && pFileIndex->fIsGoodPattern)
- {
- if (match (pSearchFor, dir[i].fname))
- {
- short numMatched = pFileIndex->numMatched;
-
-
- assert (
- pFileIndex->pMatchedIndices =
- (short *) realloc (pFileIndex->pMatchedIndices,
- (size_t) (numMatched + 1) *
- sizeof (MatchStruct)));
-
- pFileIndex->pMatchedIndices[numMatched] = i;
-
- (pFileIndex->numMatched)++;
-
- numFound++;
-
- break;
- }
- }
- else if (!strcmp (dir[i].fname, pSearchFor))
- {
- pFileIndex->fileIndex = i;
- numFound++;
- break;
- }
- }
- }
- }
- }
-
- if (numSpecFiles /* > 0 */ && numSpecFiles != numFound)
- {
- short j;
-
-
- console_options.pause_atexit = 1;
-
- for (j = 0; j < numSpecFiles; j++)
- {
- MatchPtr pFileIndex = pFileIndices + j;
-
-
- if (pFileIndex->fileIndex == -1 &&
- (!pFileIndex->fIsPattern || pFileIndex->numMatched == 0))
- fprintf (stderr, "%s: %s not found in %s.\n",
- pname, argv[optind + j], libfname);
- }
-
- if (numFound == 0)
- error ("%s: None of the specified entries were found!\n",
- (char *) NULL, (char *) NULL);
- }
-
- if (sflg || tflg || dflg || uflg) {
- if (sflg)
- printf("## filename.ext\toffset\tsize\n%s",
- "-- ------------\t------\t----\n");
- for (i = 0; i < nfiles; i++) {
- fseek(in, dir[i].offset, 0);
- dir[i].len = GetLong(in);
- dir[i].len &= 0x00ffffff;
- if (sflg)
- printf("%2d %s\t%ld\t%ld\n",
- i, dir[i].fname, dir[i].offset, dir[i].len);
- else if (tflg)
- printf("%s%c", dir[i].fname,
- (i + 1) % 4 && i + 1 < nfiles ? '\t' : '\n');
-
- if (dflg || uflg) {
- dir[i].data = (char *) malloc(dir[i].len);
- if (!dir[i].data)
- error("%s: not enough memory\n", NULL, NULL);
- fread(dir[i].data, dir[i].len, 1, in);
- }
- }
- }
- }
- if (eflg) {
- for (i = 0; i < numSpecFiles; i++)
- {
- MatchPtr pFileIndex = pFileIndices + i;
-
-
- if (pFileIndex->fileIndex != -1)
- {
- extractfile (in, dir, pFileIndex->fileIndex);
- }
- else if (pFileIndex->numMatched /* > 0 */)
- {
- short j;
-
-
- for (j = 0; j < pFileIndex->numMatched; j++)
- extractfile (in, dir, pFileIndex->pMatchedIndices[j]);
- }
- }
- fclose(in);
- } else if (aflg) {
- for (i = 0; i < nfiles; i++)
- extractfile(in, dir, i);
- fclose(in);
- } else if (dflg) {
- fclose(in);
-
- {
- FilenameStruct *pNewDir = (FilenameStruct *)
- malloc (nfiles * sizeof (FilenameStruct));
- short ithFile = 0;
-
-
- for (i = 0; i < nfiles; i++)
- {
- short j;
-
-
- /*...See if this entry is on the to-be-deleted list...*/
-
- for (j = 0; j < numSpecFiles; j++)
- {
- MatchPtr pFileIndex = pFileIndices + j;
-
-
- if (pFileIndex->fileIndex == i)
- {
- goto next_i;
- }
- else if (pFileIndex->numMatched /* > 0 */)
- {
- short j;
-
-
- for (j = 0; j < pFileIndex->numMatched; j++)
- {
- if (pFileIndex->pMatchedIndices[j] == i)
- goto next_i;
- }
- }
- }
-
- /*...Copy this entry...*/
-
- memcpy (&pNewDir[ithFile++], &dir[i], sizeof (FilenameStruct));
-
- next_i: ;
- }
-
- nfiles = ithFile;
- free ((char *) dir);
- dir = pNewDir;
- }
-
- writefile (libfname, dir, nfiles);
- } else if (uflg) {
-
- if (in)
- fclose(in);
- for (i = optind; i < argc; i++) {
- char *s = lowerstr (argv[i]);
- char *fn = strrchr(s, '/');
- int n;
- int idx;
-
- fn = (fn == 0) ? s : fn + 1;
- n = strlen (fn);
- if (n > 13)
- error("%s: '%s' is too long, must be < 13 chars.\n", s, NULL);
-
- idx = findname (dir, nfiles, fn);
-
- if (idx == -1) {
- nfiles++;
- if (!dir)
- dir = (FilenameStruct *) malloc(sizeof(FilenameStruct));
- else
- dir = (FilenameStruct *) realloc(dir,
- nfiles * sizeof(FilenameStruct));
- idx = nfiles - 1;
- } else
- free(dir[idx].data);
- memset(dir[idx].fname, 0, 14);
- memcpy(dir[idx].fname, fn, n);
- in = fopen(s, "rb");
- if (!in)
- error("%s: %s not found!\n", s, NULL);
-
- fseek(in, 0L, 2); /* eof */
- dir[idx].len = ftell(in);
- fseek(in, 0L, 0); /* bof */
- dir[idx].data = (char *) malloc(dir[idx].len);
- if (!dir[idx].data)
- error("%s: not enough memory\n", NULL, NULL);
- fread(dir[idx].data, dir[idx].len, 1, in);
- fclose(in);
- }
- writefile(libfname, dir, nfiles);
- }
-
- exit(0);
- }
-